<?php
/* AlaTracConverterRedux
*/
class AlaTracConverter {
    public $xhtml; // converted xhtml content as string

    public $file; // the file from the FullFilePath

    public $lines = array();
   
    public $ParsedLines = array();

    public $blocks = array(); 

    public $BlockTypes = array( "/^\={1}\s/" => 'h1', 
                                "/^\={2}\s/" => 'h2', 
                                "/^\={3}\s/" => 'h3', 
                                "/^\={4}\s/" => 'h4', 
                                "/^\={5}\s/" => 'h5', 
                                "/^\={6}\s/" => 'h6', 
                                "/^\|{2}/" => 'table', 
                                "/^\{{3}/" => 'pre-open', 
                                "/^\}{3}/" => 'pre-close', 
                                "/^\s+\*{1}\s{1}/" => 'ul', 
                                "/^\s+[0-9]+.\s/" => 'ol', 
                                "/^\[{2}Image\(/" => 'image',
                                "/^\n$/" => 'blank'
                                ); 

    public function __construct($FullFilePath) {
        $this->file = $FullFilePath;
        $this->create_lines();
        $this->parse_lines();
        $this->create_blocks();
        $this->xhtml = $this->convert_inline_links($this->xhtml);
        $this->xhtml = $this->convert_inline_code($this->xhtml);
        $this->xhtml = '<div class="main-content">' . $this->xhtml . '</div>';
    }

    public function create_lines() {
        // take the file and create an array of lines
        $content = file_get_contents($this->file);
        // take the text content and break by line breaks
        $this->lines = explode("\n", $content);
    }

    /* function that parses each line in the lines array
     * and determines what kind of block this is
     */
    public function parse_lines() {
        foreach ($this->lines as $line) {
            // get the line content, blocktype returned, and push to the ParsedLines array
            $ThisLine = array();
            $ThisLine['blocktype'] = $this->determine_block_type($line);
            $ThisLine['content'] = $line;
            array_push($this->ParsedLines, $ThisLine);
        }
    }

    /* determine what kind of block this is */
    public function determine_block_type($line) {
        foreach ($this->BlockTypes as $key => $value) {
            if (preg_match($key, $line)) {
                return $value;
                break 2;
            }
        }
    }

    /* take the parsed lines and separate single and multi-lined elements into blocks */
    public function create_blocks() {
        // start with a newline
        $this->xhtml = "
";        
        $preblock = false; // set pre block to false
        // go through each line and determine single or multiline rule depending on blocktype
        for ($o = 0; $o<count($this->ParsedLines); $o++) {
            $blocktype = $this->ParsedLines[$o]['blocktype'];
            $content = $this->ParsedLines[$o]['content'];
            // go through the types
            switch ($blocktype) {
                case 'h1':        
                $content = trim($this->ParsedLines[$o]['content']);
                $this->xhtml .= '<h1>' . substr($content, 2, -2) . '</h1>
';
                break;
                case 'h2':            
                $content = trim($this->ParsedLines[$o]['content']);
                $this->xhtml .= '<h2>' . substr($content, 3, -3) . '</h2>
';
                break;   
                case 'h3':              
                $content = trim($this->ParsedLines[$o]['content']);
                $this->xhtml .= '<h3>' . substr($content, 4, -4) . '</h3>
';
                break;
                case 'ol':
                /*
                // if previous line's block type is '' only, start a ol tag
                // if next line's block type is '' only, end the ol tag
                // if previous and bext lines are '', start and end ol tags
                // otherwise do not precede and end with opening and ending ol tags
                */    
                $content = preg_replace("/^\s+[0-9]+\.\s{1}/","",$content);
                if ($this->ParsedLines[$o - 1]['blocktype'] == '' && $this->ParsedLines[$o + 1]['blocktype'] != '') {
                    $this->xhtml .= "
<ol>
  <li>$content</li>";
                } 
                else if ($this->ParsedLines[$o - 1]['blocktype'] != '' && $this->ParsedLines[$o + 1]['blocktype'] == '') {
                    $this->xhtml .= "
  <li>$content</li>
</ol>
";
                } 
                else if ($this->ParsedLines[$o - 1]['blocktype'] == '' && $this->ParsedLines[$o + 1]['blocktype'] == '') {
                    $this->xhtml .= "
<ol>
  <li>$content</li>
</ol>
";
                }
                else {
                    $this->xhtml .= "
  <li>$content</li>                    
                    ";
                }
                break;
                case 'ul':   
                /*
                // if previous line's block type is '' only, start a ul tag
                // if next line's block type is '' only, end the ul tag
                // if previous and bext lines are '', start and end ul tags
                // otherwise do not precede and end with opening and ending ul tags 
                */
                if (!isset($spaces)) {
                    $spaces = strpos($content,"* ");
                    $init = $spaces; // so we know where we are starting from
                }
                else {
                    if ($spaces == strpos($content, "* ")) {
                        // same number of preceding spaces
                        $step = 'idle';
                        $spaces = strpos($content, "* ");
                    }
                    else if ($spaces > strpos($content, "* ")) {
                        // greater than
                        $step = 'open';
                        $spaces = strpos($content, "* ");
                    }
                    else {
                        // less than
                        $step = 'close';
                        $spaces = strpos($content, "* ");
                    }
                }
                // print "<p>UL spaces: $spaces </p>";
                $content = preg_replace("/^\s+\*{1}\s{1}/","",$content);
                if ($this->ParsedLines[$o - 1]['blocktype'] == '' && $this->ParsedLines[$o + 1]['blocktype'] != '') {
                    // if previous line's block type is '' only, start a ul tag
                    $this->xhtml .= "
<ul>
  <li>$content</li>";
                } 
                else if ($this->ParsedLines[$o - 1]['blocktype'] != '' && $this->ParsedLines[$o + 1]['blocktype'] == '') {
                    // if next line's block type is '' only, end the ul tag, check the spaces and compare to init value
                    // divide spaces by init, and use the result as how many closing tags to add
                    $this->xhtml .= "
  <li>$content</li>
</ul>
";
                } 
                else if ($this->ParsedLines[$o - 1]['blocktype'] == '' && $this->ParsedLines[$o + 1]['blocktype'] == '') {
                    // if previous and bext lines are '', start and end ul tags
                    $this->xhtml .= "
<ul>
  <li>$content</li>
</ul>
";
                }
                else {
                    // otherwise do not precede and end with opening and ending ul tags
                    $this->xhtml .= "
  <li>$content</li>                    
                    ";
                }
                break;
                case 'table':    
                /*
                // if previous line's block type is '' only, start a table tag
                // if next line's block type is '' only, end the table tag
                // if previous and bext lines are '', start and end table tags
                // otherwise do not precede and end with opening and ending table tags 
                */
                $content = substr($content, 2, -2);
                $content = preg_replace("/\|{2}/","</td><td>",$content);
                if ($this->ParsedLines[$o - 1]['blocktype'] == '' && $this->ParsedLines[$o + 1]['blocktype'] != '') {
                    $this->xhtml .= "
<table>
  <tr><td>$content</td></tr>";
                }
                else if ($this->ParsedLines[$o - 1]['blocktype'] != '' && $this->ParsedLines[$o + 1]['blocktype'] == '') {
                     $this->xhtml .= "
  <tr><td>$content</td></tr>
</table>  
";
                }
                else if ($this->ParsedLines[$o - 1]['blocktype'] == '' && $this->ParsedLines[$o + 1]['blocktype'] != '') {
                      $this->xhtml .= "
<table>
  <tr><td>$content</td></tr>
</table>                    
";
                }
                else {
                      $this->xhtml .= "
  <tr><td>$content</td></tr>";
                }
                break;
                case 'image':
                    $this->xhtml .= $this->convert_images($this->ParsedLines[$o]['content']);
                break;
                case 'pre-open':
                // set preblock to true
                $preblock = true;
                $this->xhtml .= '<pre>
';
                break;
                case 'pre-close':
                // set preblock to false
                $preblock = false;
                $this->xhtml .= '</pre>
';
                break;
                case '':
                // check to see if $preblock is true
                if ($preblock) {
                    // return the line as is
                    $this->xhtml .= htmlentities($content) . "
";
                }
                else
                {
                    if ($content == "\n" || $content != "") {
                        $this->xhtml .= "<p>$content</p>
";                  
                    }
                }
            }
        }
    }

    /* convert inline links */
    public function convert_inline_links($line) {
        $newLine = $line;
        $linkPattern = "/\[[0-9a-zA-Z.(\/)(\:)(\~)]+\s[0-9a-zA-Z(\s)]+\]/";
        preg_match_all($linkPattern, $line, $linkMatch);
        
        // for each found match, create a key value pair of itself as key and the replacement as value
        foreach ($linkMatch as $match) {
            foreach ($match as $k => $v) {
                $replacement = "<a href='" . substr($v, 1, stripos($v, " ")) . "'>" . substr($v, stripos($v, " "), -1) . "</a>";
                $newLine = str_replace($v, $replacement, $newLine);
            }
        }
        // print $newLine;
        return $newLine;
    }

    /* convert images */
    public function convert_images($string) {
        $imagePattern = "/\[{2}Image\([a-zA-Z0-9.\:\/]+\)\]{2}/";
        $url = str_replace("[[Image(","",$string);
        $url = str_replace(")]]","",$url);
        return "<img src='$url'/>";
    }

    /* convert inline code */
    public function convert_inline_code($line) {
        $codePattern = "/\{{3}(?!\{\{\{).+\}{3}/";
        preg_match_all($codePattern, $line, $codeMatch);
        
        foreach ($codeMatch as $match) {
            foreach ($match as $k => $v) {
                $codeString = htmlentities($v); // get rid of actual code characters
                $codeString = str_replace("{{{","<span class='inline-code'>",$codeString);
                $replacement = str_replace("}}}","</span>",$codeString);
                $line = str_replace($v, $replacement, $line);
            }
        }
        // for now, look for the opening tags, then start an htmlentities process, then look for the closing 
        return $line; 
    }
}

/*
$atc = new AlaTracConverter('AlaTracConverter.wiki');

print '<pre>';
print_r($atc->ParsedLines);
print '</pre>';

// print out the xhtml to see
print $atc->xhtml;
*/
